package com.lhb.boyixue.user.utils;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import okhttp3.*;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author 86131
 * @version 1.0
 * @description 讯飞星火语音转文字工具
 * @date 2025/6/17 下午11:08
 */
/**
 * 讯飞语音识别工具类
 * 基于原始WebSocket代码改造
 */
public class XunfeiSpeechTool {
    private static final String hostUrl = "https://iat-api.xfyun.cn/v2/iat";
    private static final String appid = "f797dc2e"; // 替换为你的APPID
    private static final String apiSecret = "MjAxMDViMTI4MWVkNzM0MDkzMWY2NzI1"; // 替换为你的APISecret
    private static final String apiKey = "93a22ed5ac9135177f63332244985690"; // 替换为你的APIKey

    public static final int StatusFirstFrame = 0;
    public static final int StatusContinueFrame = 1;
    public static final int StatusLastFrame = 2;
    public static final Gson json = new Gson();

    /**
     * 识别音频文件
     *
     * @param audioData 音频字节数组
     * @return 识别结果文本
     */
    public static String recognizeAudio(byte[] audioData) throws Exception {
        CompletableFuture<String> future = new CompletableFuture<>();

        // 构建鉴权url
        String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        OkHttpClient client = new OkHttpClient.Builder().build();
        String url = authUrl.replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();

        WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
            Decoder decoder = new Decoder();

            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                super.onOpen(webSocket, response);
                System.out.println("WebSocket连接建立");

                // 发送音频数据
                new Thread(() -> {
                    try {
                        sendAudioData(webSocket, audioData, decoder);
                    } catch (Exception e) {
                        future.completeExceptionally(e);
                    }
                }).start();
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {
                super.onMessage(webSocket, text);

                ResponseData resp = json.fromJson(text, ResponseData.class);
                if (resp != null) {
                    if (resp.getCode() != 0) {
                        System.err.println("错误: code=" + resp.getCode() + " message=" + resp.getMessage());
                        future.completeExceptionally(new RuntimeException(resp.getMessage()));
                        return;
                    }

                    if (resp.getData() != null) {
                        if (resp.getData().getResult() != null) {
                            Text te = resp.getData().getResult().getText();
                            try {
                                decoder.decode(te);
                                System.out.println("识别中: " + decoder.toString());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                        if (resp.getData().getStatus() == 2) {
                            // 识别完成
                            String result = decoder.toString();
                            System.out.println("最终识别结果: " + result);
                            future.complete(result);
                            webSocket.close(1000, "");
                        }
                    }
                }
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                super.onFailure(webSocket, t, response);
                System.err.println("WebSocket连接失败: " + t.getMessage());
                future.completeExceptionally(t);
            }
        });

        // 等待结果（最多30秒）
        try {
            return future.get(30, java.util.concurrent.TimeUnit.SECONDS);
        } catch (Exception e) {
            webSocket.close(1000, "");
            throw new RuntimeException("识别超时或失败", e);
        }
    }

    /**
     * 发送音频数据（基于原始代码改造）
     */
    private static void sendAudioData(WebSocket webSocket, byte[] audioData, Decoder decoder) throws InterruptedException {
        int frameSize = 1280; // 每一帧音频的大小
        int interval = 40; // 间隔时间
        int status = StatusFirstFrame;
        int offset = 0;

        while (offset < audioData.length) {
            int len = Math.min(frameSize, audioData.length - offset);
            byte[] buffer = Arrays.copyOfRange(audioData, offset, offset + len);

            if (offset + len >= audioData.length) {
                status = StatusLastFrame; // 最后一帧
            }

            switch (status) {
                case StatusFirstFrame: // 第一帧
                    JsonObject frame = new JsonObject();
                    JsonObject business = new JsonObject();
                    JsonObject common = new JsonObject();
                    JsonObject data = new JsonObject();

                    // 填充common
                    common.addProperty("app_id", appid);

                    // 填充business
                    business.addProperty("language", "zh_cn");
                    business.addProperty("domain", "iat");
                    business.addProperty("accent", "mandarin");
                    business.addProperty("dwa", "wpgs");

                    // 填充data
                    data.addProperty("status", StatusFirstFrame);
                    data.addProperty("format", "audio/L16;rate=16000");
                    data.addProperty("encoding", "raw");
                    data.addProperty("audio", Base64.getEncoder().encodeToString(buffer));

                    // 填充frame
                    frame.add("common", common);
                    frame.add("business", business);
                    frame.add("data", data);
                    webSocket.send(frame.toString());
                    status = StatusContinueFrame;
                    break;

                case StatusContinueFrame: // 中间帧
                    JsonObject frame1 = new JsonObject();
                    JsonObject data1 = new JsonObject();
                    data1.addProperty("status", StatusContinueFrame);
                    data1.addProperty("format", "audio/L16;rate=16000");
                    data1.addProperty("encoding", "raw");
                    data1.addProperty("audio", Base64.getEncoder().encodeToString(buffer));
                    frame1.add("data", data1);
                    webSocket.send(frame1.toString());
                    break;

                case StatusLastFrame: // 最后一帧
                    JsonObject frame2 = new JsonObject();
                    JsonObject data2 = new JsonObject();
                    data2.addProperty("status", StatusLastFrame);
                    data2.addProperty("audio", "");
                    data2.addProperty("format", "audio/L16;rate=16000");
                    data2.addProperty("encoding", "raw");
                    frame2.add("data", data2);
                    webSocket.send(frame2.toString());
                    System.out.println("音频发送完成");
                    return;
            }

            offset += len;
            Thread.sleep(interval); // 模拟音频采样延时
        }
    }

    // 以下是你的原始代码中的方法和类定义，保持不变

    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n")
                .append("date: ").append(date).append("\n")
                .append("GET ").append(url.getPath()).append(" HTTP/1.1");

        Charset charset = Charset.forName("UTF-8");
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
        String sha = Base64.getEncoder().encodeToString(hexDigits);

        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
                apiKey, "hmac-sha256", "host date request-line", sha);

        HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder()
                .addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset)))
                .addQueryParameter("date", date)
                .addQueryParameter("host", url.getHost())
                .build();
        return httpUrl.toString();
    }

    // 原始数据类定义
    public static class ResponseData {
        private int code;
        private String message;
        private String sid;
        private Data data;

        public int getCode() {
            return code;
        }

        public String getMessage() {
            return this.message;
        }

        public String getSid() {
            return sid;
        }

        public Data getData() {
            return data;
        }
    }

    public static class Data {
        private int status;
        private Result result;

        public int getStatus() {
            return status;
        }

        public Result getResult() {
            return result;
        }
    }

    public static class Result {
        int bg, ed, sn;
        String pgs;
        int[] rg;
        Ws[] ws;
        boolean ls;
        JsonObject vad;

        public Text getText() {
            Text text = new Text();
            StringBuilder sb = new StringBuilder();
            for (Ws ws : this.ws) {
                sb.append(ws.cw[0].w);
            }
            text.sn = this.sn;
            text.text = sb.toString();
            text.rg = this.rg;
            text.pgs = this.pgs;
            text.bg = this.bg;
            text.ed = this.ed;
            text.ls = this.ls;
            text.vad = this.vad;
            return text;
        }
    }

    public static class Ws {
        Cw[] cw;
        int bg, ed;
    }

    public static class Cw {
        int sc;
        String w;
    }

    public static class Text {
        int sn, bg, ed;
        String text, pgs;
        int[] rg;
        boolean deleted, ls;
        JsonObject vad;
    }

    // 解析返回数据的解码器（你的原始代码）
    public static class Decoder {
        private Text[] texts;
        private int defc = 10;

        public Decoder() {
            this.texts = new Text[this.defc];
        }

        public synchronized void decode(Text text) {
            if (text.sn >= this.defc) {
                this.resize();
            }
            if ("rpl".equals(text.pgs)) {
                for (int i = text.rg[0]; i <= text.rg[1]; i++) {
                    this.texts[i].deleted = true;
                }
            }
            this.texts[text.sn] = text;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            for (Text t : this.texts) {
                if (t != null && !t.deleted) {
                    sb.append(t.text);
                }
            }
            return sb.toString();
        }

        public void resize() {
            int oc = this.defc;
            this.defc <<= 1;
            Text[] old = this.texts;
            this.texts = new Text[this.defc];
            for (int i = 0; i < oc; i++) {
                this.texts[i] = old[i];
            }
        }

        public void discard() {
            for (int i = 0; i < this.texts.length; i++) {
                this.texts[i] = null;
            }
        }
    }
}